#ifndef __XFCE_PANEL_EXTERNAL_PLUGIN_H__
#define __XFCE_PANEL_EXTERNAL_PLUGIN_H__

#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>


G_BEGIN_DECLS


/* if defined, the source will be compiled not as an applet but as own window 
#define DEBUG_NOT_APPLET 1*/


typedef struct _XfceExternalPanelPlugin      XfceExternalPanelPlugin;
typedef struct _XfceExternalPanelPluginClass XfceExternalPanelPluginClass;

typedef void (*XfceExternalPanelPluginFunc) (XfceExternalPanelPlugin *plugin);


#define XFCE_EXTERNAL_PANEL_PLUGIN_TYPE            (xfce_external_panel_plugin_get_type())
#define XFCE_EXTERNAL_PANEL_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_EXTERNAL_PANEL_PLUGIN_TYPE, XfceExternalPanelPlugin))
#define XFCE_EXTERNAL_PANEL_PLUGIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_EXTERNAL_PANEL_PLUGIN_TYPE, XfceExternalPanelPluginClass))
#define XFCE_IS_EXTERNAL_PANEL_PLUGIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_EXTERNAL_PANEL_PLUGIN))
#define XFCE_IS_EXTERNAL_PANEL_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_EXTERNAL_PANEL_PLUGIN))
#define XFCE_EXTERNAL_PANEL_PLUGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_EXTERNAL_PANEL_PLUGIN, XfceExternalPanelPluginClass))


struct _XfceExternalPanelPlugin
{
#ifdef DEBUG_NOT_APPLET
    GtkWindow parent;
#else
    GtkPlug parent;
#endif
};

struct _XfceExternalPanelPluginClass
{
#ifdef DEBUG_NOT_APPLET
    GtkWindowClass parent_class;
#else
    GtkPlugClass parent;
#endif
};


GType 
xfce_external_panel_plugin_get_type  (void) G_GNUC_CONST;

GtkWidget *
xfce_external_panel_plugin_new(gint argc,gchar **argv,XfceExternalPanelPluginFunc construct) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;


void 
xfce_panel_plugin_menu_show_configure(XfceExternalPanelPlugin *plugin);

void 
xfce_panel_plugin_menu_show_about(XfceExternalPanelPlugin *plugin);

GtkWidget* 
xfce_hvbox_new(GtkOrientation orientation,gboolean homogeneous,gint spacing);


void 
xfce_panel_plugin_block_menu (XfceExternalPanelPlugin *plugin);

void 
xfce_panel_plugin_unblock_menu (XfceExternalPanelPlugin *plugin);


char * 
xfce_panel_plugin_lookup_rc_file(XfceExternalPanelPlugin *plugin);

char * 
xfce_panel_plugin_save_location(gpointer a, gboolean b);


GtkOrientation  
xfce_panel_plugin_get_orientation(XfceExternalPanelPlugin *plugin);


void
xfce_panel_plugin_add_action_widget (XfceExternalPanelPlugin *plugin,GtkWidget *widget);

void  
xfce_panel_plugin_menu_insert_item(XfceExternalPanelPlugin *plugin, GtkMenuItem *item);

gint  
xfce_panel_plugin_get_size(XfceExternalPanelPlugin *plugin);



typedef gboolean (*XfcePanelPluginCheck) (GdkScreen *screen);
typedef gboolean (*XfcePanelPluginPreInit) (int argc, char **argv);

#define XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL(construct)  \
    XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL_FULL(construct,NULL,NULL)

#define XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL_WITH_CHECK(construct,check) \
    XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL_FULL(construct,NULL,check)

#define XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL_FULL(construct,init,check)	\
    gint								\
    main (gint argc, gchar **argv)					\
    {									\
    GtkWidget              *plugin;					\
    XfceExternalPanelPluginFunc  create  = (XfceExternalPanelPluginFunc) construct; \
    XfcePanelPluginPreInit  preinit = (XfcePanelPluginPreInit) init;	\
    XfcePanelPluginCheck    test    = (XfcePanelPluginCheck) check;	\
									\
    if ( preinit )							\
    {									\
	if (G_UNLIKELY (preinit(argc,argv) == FALSE))			\
	  return 3;							\
    }									\
    gtk_init (&argc, &argv);						\
									\
    if ( test )								\
    {									\
	if (G_UNLIKELY (test(gdk_screen_get_default()) == FALSE))	\
	  return 2;							\
    }									\
    if ( g_getenv("APP_DIR")==NULL ){					\
	fputs("Use AppletRun to start this plugin\n",stderr);		\
	return 1;							\
    }									\
    plugin = xfce_external_panel_plugin_new (argc, argv, create);	\
    if (G_UNLIKELY (plugin == NULL)){					\
	  fputs("plugin_new failed\n",stderr);				\
	  return 1;							\
    }									\
    g_signal_connect_after (G_OBJECT (plugin), "destroy",		\
			    G_CALLBACK (gtk_main_quit), NULL);		\
    gtk_widget_show (plugin);						\
        gtk_main ();							\
									\
        return 0;							\
    }


#define XFCE_PANEL_PLUGIN_REGISTER_INTERNAL_REAL XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL
#define XFCE_PANEL_PLUGIN_REGISTER_INTERNAL XFCE_PANEL_PLUGIN_REGISTER_INTERNAL_REAL 

/* dummy macros: there are only external plugins - no need for a common inteface for external and internal plugins 
   and plugins don't change their orientation: no need for xfcehvbox ... */

#define XfceHVBox GtkBox
#define XfcePanelPlugin XfceExternalPanelPlugin
#define XFCE_HVBOX(a) GTK_BOX(a)


/* not (yet?) supported functions:*/

/*void xfce_hvbox_set_orientation(XfceHVBox *hvbox,GtkOrientation orientation) */
#define xfce_hvbox_set_orientation(hvbox,orientation) do{}while(0)

/*void xfce_panel_plugin_set_panel_hidden (XfcePanelPlugin *plugin, gboolean hidden);*/
#define xfce_panel_plugin_set_panel_hidden(plugin,hidden) do{}while(0)

/*void xfce_panel_plugin_register_menu (XfcePanelPlugin *plugin, GtkMenu *menu);*/
#define xfce_panel_plugin_register_menu(plugin,menu) do{}while(0)

#define xfce_panel_plugin_set_expand(a,b) do {} while(0)


/* unsupported enums/macros, that are not supported yet */
#ifdef ROX_PLUGIN_SUPPORT_SCREEN_POSITION

GType xfce_screen_position_get_type (void) G_GNUC_CONST;
#define XFCE_TYPE_SCREEN_POSITION (xfce_screen_position_get_type())


typedef enum /*<enum,prefix=XFCE_SCREEN_POSITION >*/
{
    XFCE_SCREEN_POSITION_NONE,
    XFCE_SCREEN_POSITION_NW_H,          /* North West Horizontal */
    XFCE_SCREEN_POSITION_N,             /* North                 */
    XFCE_SCREEN_POSITION_NE_H,          /* North East Horizontal */
    XFCE_SCREEN_POSITION_NW_V,          /* North West Vertical   */
    XFCE_SCREEN_POSITION_W,             /* West                  */
    XFCE_SCREEN_POSITION_SW_V,          /* South West Vertical   */
    XFCE_SCREEN_POSITION_NE_V,          /* North East Vertical   */
    XFCE_SCREEN_POSITION_E,             /* East                  */
    XFCE_SCREEN_POSITION_SE_V,          /* South East Vertical   */
    XFCE_SCREEN_POSITION_SW_H,          /* South West Horizontal */
    XFCE_SCREEN_POSITION_S,             /* South                 */
    XFCE_SCREEN_POSITION_SE_H,          /* South East Horizontal */
    XFCE_SCREEN_POSITION_FLOATING_H,    /* Floating Horizontal */
    XFCE_SCREEN_POSITION_FLOATING_V     /* Floating Vertical */
} XfceScreenPosition;

/*this should be implemented,...
XfceScreenPosition  xfce_panel_plugin_get_screen_position(XfcePanelPlugin *plugin);*/
#define xfce_panel_plugin_get_screen_position(plugin) XFCE_SCREEN_POSITION_S

#define xfce_screen_position_is_horizontal(position)   \
    (position <= XFCE_SCREEN_POSITION_NE_H ||          \
     (position >= XFCE_SCREEN_POSITION_SW_H &&         \
      position <= XFCE_SCREEN_POSITION_FLOATING_H))

#define xfce_screen_position_get_orientation(position)	\
    (xfce_screen_position_is_horizontal (position) ?		\
     GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL)

#define xfce_screen_position_is_floating(position) \
    (position >= XFCE_SCREEN_POSITION_FLOATING_H || \
     position == XFCE_SCREEN_POSITION_NONE)

#define xfce_screen_position_is_top(position) \
    (position >= XFCE_SCREEN_POSITION_NW_H && \
     position <= XFCE_SCREEN_POSITION_NE_H)

#define xfce_screen_position_is_left(position) \
    (position >= XFCE_SCREEN_POSITION_NW_V && \
     position <= XFCE_SCREEN_POSITION_SW_V)

#define xfce_screen_position_is_right(position) \
    (position >= XFCE_SCREEN_POSITION_NE_V && \
     position <= XFCE_SCREEN_POSITION_SE_V)

#define xfce_screen_position_is_bottom(position) \
    (position >= XFCE_SCREEN_POSITION_SW_H)

#endif // ROX_PLUGIN_SUPPORT_SCREEN_POSITION







/*panel-macros*/


/* Support macro's for the slice allocator */
#if GLIB_CHECK_VERSION(2,10,0)
#define panel_slice_alloc(block_size)             (g_slice_alloc ((block_size)))
#define panel_slice_alloc0(block_size)            (g_slice_alloc0 ((block_size)))
#define panel_slice_free1(block_size, mem_block)  G_STMT_START{ g_slice_free1 ((block_size), (mem_block)); }G_STMT_END
#define panel_slice_new(type)                     (g_slice_new (type))
#define panel_slice_new0(type)                    (g_slice_new0 (type))
#define panel_slice_free(type, ptr)               G_STMT_START{ g_slice_free (type, (ptr)); }G_STMT_END
#else
#define panel_slice_alloc(block_size)             (g_malloc ((block_size)))
#define panel_slice_alloc0(block_size)            (g_malloc0 ((block_size)))
#define panel_slice_free1(block_size, mem_block)  G_STMT_START{ g_free ((mem_block)); }G_STMT_END
#define panel_slice_new(type)                     (g_new (type, 1))
#define panel_slice_new0(type)                    (g_new0 (type, 1))
#define panel_slice_free(type, ptr)               G_STMT_START{ g_free ((ptr)); }G_STMT_END
#endif



/* Canonical Strings */
#if GLIB_CHECK_VERSION(2,10,0)
#define I_(string) (g_intern_static_string ((string)))
#else
#define I_(string) (g_quark_to_string (g_quark_from_static_string ((string))))
#endif



#if GLIB_CHECK_VERSION(2,7,0)
#define PANEL_PARAM_READABLE  (G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
#define PANEL_PARAM_WRITABLE  (G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
#define PANEL_PARAM_READWRITE (G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
#else
#define PANEL_PARAM_READABLE  (G_PARAM_READABLE)
#define PANEL_PARAM_WRITABLE  (G_PARAM_WRITABLE)
#define PANEL_PARAM_READWRITE (G_PARAM_READWRITE)
#endif


/* support macros for debugging */
#ifndef NDEBUG
#define _panel_assert(expr)                  g_assert (expr)
#define _panel_assert_not_reached()          g_assert_not_reached ()
#define _panel_return_if_fail(expr)          g_return_if_fail (expr)
#define _panel_return_val_if_fail(expr, val) g_return_val_if_fail (expr, (val))
#else
#define _panel_assert(expr)                  G_STMT_START{ (void)0; }G_STMT_END
#define _panel_assert_not_reached()          G_STMT_START{ (void)0; }G_STMT_END
#define _panel_return_if_fail(expr)          G_STMT_START{ (void)0; }G_STMT_END
#define _panel_return_val_if_fail(expr, val) G_STMT_START{ (void)0; }G_STMT_END
#endif


/* avoid trivial g_value_get_*() function calls */
#ifdef NDEBUG
#define g_value_get_boolean(v)  (((const GValue *) (v))->data[0].v_int)
#define g_value_get_char(v)     (((const GValue *) (v))->data[0].v_int)
#define g_value_get_uchar(v)    (((const GValue *) (v))->data[0].v_uint)
#define g_value_get_int(v)      (((const GValue *) (v))->data[0].v_int)
#define g_value_get_uint(v)     (((const GValue *) (v))->data[0].v_uint)
#define g_value_get_long(v)     (((const GValue *) (v))->data[0].v_long)
#define g_value_get_ulong(v)    (((const GValue *) (v))->data[0].v_ulong)
#define g_value_get_int64(v)    (((const GValue *) (v))->data[0].v_int64)
#define g_value_get_uint64(v)   (((const GValue *) (v))->data[0].v_uint64)
#define g_value_get_enum(v)     (((const GValue *) (v))->data[0].v_long)
#define g_value_get_flags(v)    (((const GValue *) (v))->data[0].v_ulong)
#define g_value_get_float(v)    (((const GValue *) (v))->data[0].v_float)
#define g_value_get_double(v)   (((const GValue *) (v))->data[0].v_double)
#define g_value_get_string(v)   (((const GValue *) (v))->data[0].v_pointer)
#define g_value_get_param(v)    (((const GValue *) (v))->data[0].v_pointer)
#define g_value_get_boxed(v)    (((const GValue *) (v))->data[0].v_pointer)
#define g_value_get_pointer(v)  (((const GValue *) (v))->data[0].v_pointer)
#define g_value_get_object(v)   (((const GValue *) (v))->data[0].v_pointer)
#endif



/* don't use the invalid property warning since testing in debug builds is enough */
#ifndef G_ENABLE_DEBUG
#undef G_OBJECT_WARN_INVALID_PROPERTY_ID
#define G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec) G_STMT_START{ (void)0; }G_STMT_END
#endif








G_END_DECLS


#endif
